package com.todo.delicacy.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.todo.common.common.entity.response.BizResponse;
import com.todo.common.common.entity.response.page.PageResult;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.enums.EnableTypeEnum;
import com.todo.common.common.exception.BizException;
import com.todo.common.utils.StringUtils;
import com.todo.delicacy.application.convert.FoodConvert;
import com.todo.delicacy.application.entity.bo.RestaurantDetailBO;
import com.todo.delicacy.application.entity.bo.RestaurantInfoBO;
import com.todo.delicacy.application.entity.condition.RestaurantInfoConditionBO;
import com.todo.delicacy.application.remote.SightPoiRemote;
import com.todo.delicacy.application.service.RestaurantInfoService;
import com.todo.delicacy.infrastructure.entity.condition.RestaurantInfoCondition;
import com.todo.delicacy.infrastructure.entity.po.RestaurantInfoPO;
import com.todo.delicacy.infrastructure.repository.RestaurantInfoRepository;
import com.todo.sight.service.api.request.QuerySightPoiByIdRequest;
import com.todo.sight.service.api.response.SightPoiDetailResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (RestaurantInfo)表服务实现类
 *
 * @author zhangwenxiang
 * @since 2024-03-04 00:19:48
 */
@Slf4j
@Service("restaurantInfoService")
public class RestaurantInfoServiceImpl implements RestaurantInfoService {

    public static final int MAX_QUERY_PAGE_SIZE = 100;

    @Resource
    private RestaurantInfoRepository restaurantInfoRepository;
    @Resource
    private SightPoiRemote sightPoiRemote;

    @Override
    public Boolean insertRestaurantInfo(RestaurantInfoBO restaurantInfoBO) {
        if (restaurantInfoBO == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        RestaurantInfoPO alreadyRestaurantInfoPO = restaurantInfoRepository.queryRestaurantInfoByPoiId(restaurantInfoBO.getStorePoiId());
        if (alreadyRestaurantInfoPO != null) {
            log.warn("RestaurantInfoService#insertRestaurantInfo 新增饭店信息失败，当前POI信息已经被使用 restaurantInfoBO：【{}】", JSONObject.toJSONString(restaurantInfoBO));
            throw new BizException(BizErrorCodeEnum.SUCCESS_EXIST, "当前POI信息已经被使用");
        }
        RestaurantInfoPO restaurantInfoPO = FoodConvert.convertToRestaurantInfoPO(restaurantInfoBO);
        Boolean insertResult = restaurantInfoRepository.insertRestaurantInfoPO(restaurantInfoPO);
        return insertResult;
    }

    @Override
    public Boolean updateRestaurantInfo(RestaurantInfoBO restaurantInfoBO) {
        if (restaurantInfoBO == null || restaurantInfoBO.getRestaurantId() == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        RestaurantInfoBO alreadyRestaurantInfoBO = queryRestaurantInfoById(restaurantInfoBO.getRestaurantId());
        if (alreadyRestaurantInfoBO == null) {
            log.warn("RestaurantInfoService#updateRestaurantInfo 更新饭店信息失败，数据不存在 restaurantInfoBO：【{}】", JSONObject.toJSONString(restaurantInfoBO));
            throw new BizException(BizErrorCodeEnum.DATA_NOT_EXIST);
        }
        if (!alreadyRestaurantInfoBO.getStorePoiId().equals(restaurantInfoBO.getStorePoiId())) {
            //todo 后续需要针对poi的信息验证当前饭店省市区是否正确
            RestaurantInfoPO alreadyRestaurantInfoPO = restaurantInfoRepository.queryRestaurantInfoByPoiId(restaurantInfoBO.getStorePoiId());
            if (alreadyRestaurantInfoPO != null) {
                log.warn("RestaurantInfoService#updateRestaurantInfo 更新饭店信息失败，当前POI信息已经被使用 restaurantInfoBO：【{}】", JSONObject.toJSONString(restaurantInfoBO));
                throw new BizException(BizErrorCodeEnum.SUCCESS_EXIST, "当前POI信息已经被使用");
            }
        }
        RestaurantInfoPO restaurantInfoPO = FoodConvert.convertToRestaurantInfoPO(restaurantInfoBO);
        Boolean updateResult = restaurantInfoRepository.updateRestaurantInfoPOById(restaurantInfoPO);
        return updateResult;
    }

    @Override
    public Boolean removeRestaurantInfoById(Long restaurantId) {
        if (restaurantId == null || restaurantId <= 0) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        RestaurantInfoBO restaurantInfoBO = queryRestaurantInfoById(restaurantId);
        if (restaurantInfoBO == null) {
            log.info("RestaurantInfoService#removeRestaurantInfoById 删除饭店完成，根据主键查询为空，默认成功 restaurantId：【{}】", restaurantId);
            return true;
        }
        return restaurantInfoRepository.removeRestaurantInfoPOById(restaurantId);
    }

    @Override
    public Boolean updateRestaurantOpenStatus(Long restaurantId, EnableTypeEnum status) {
        if (restaurantId == null || restaurantId <= 0 || status == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        RestaurantInfoBO restaurantInfoBO = queryRestaurantInfoById(restaurantId);
        if (restaurantInfoBO == null) {
            log.warn("RestaurantInfoService#updateRestaurantOpenStatus 更新饭店状态失败，数据不存在 restaurantId：【{}】", restaurantId);
            throw new BizException(BizErrorCodeEnum.DATA_NOT_EXIST);
        }
        if (restaurantInfoBO.getIsOpen().equals(status)) {
            log.info("RestaurantInfoService#updateRestaurantOpenStatus 更新饭店状态完成，当前状态和数据状态一致，默认不操作 restaurantId：【{}】，status：【{}】", restaurantId, status);
            return true;
        }
        restaurantInfoBO.setIsOpen(status);
        return updateRestaurantInfo(restaurantInfoBO);
    }

    @Override
    public RestaurantInfoBO queryRestaurantInfoById(Long restaurantId) {
        if (restaurantId == null || restaurantId <= 0) {
            return null;
        }
        RestaurantInfoPO restaurantInfoPO = restaurantInfoRepository.queryRestaurantInfoPOById(restaurantId);
        return FoodConvert.convertToRestaurantInfoBO(restaurantInfoPO);
    }

    @Override
    public RestaurantDetailBO queryRestaurantDetailById(Long restaurantId) {
        RestaurantInfoBO restaurantInfoBO = queryRestaurantInfoById(restaurantId);
        if (restaurantInfoBO == null) {
            log.warn("RestaurantInfoService#queryRestaurantDetailById 根据饭店Id查询饭店详情信息失败，数据为空 restaurantId：【{}】", restaurantId);
            return null;
        }
        QuerySightPoiByIdRequest request = new QuerySightPoiByIdRequest();
        request.setPoiId(restaurantInfoBO.getStorePoiId());
        BizResponse<SightPoiDetailResponse> bizResponse = sightPoiRemote.querySightPoiById(request);
        if (bizResponse == null || !bizResponse.isSuccess() || bizResponse.getData() == null) {
            log.error("RestaurantInfoService#queryRestaurantDetailById 根据POI查询详情失败，数据为空 入参：【{}】，出参：【{}】", JSONObject.toJSONString(request), JSONObject.toJSONString(bizResponse));
            return null;
        }

        return FoodConvert.convertToRestaurantDetailBO(restaurantInfoBO, bizResponse.getData());
    }

    @Override
    public RestaurantDetailBO queryRestaurantDetailByPoiId(Long PoiId) {
        if (PoiId == null || PoiId <= 0) {
            return null;
        }
        RestaurantInfoPO restaurantInfoPO = restaurantInfoRepository.queryRestaurantInfoByPoiId(PoiId);
        if (restaurantInfoPO == null) {
            log.warn("RestaurantInfoService#queryRestaurantDetailByPoiId 根据PoiId查询饭店详情信息失败，数据为空 PoiId：【{}】", PoiId);
            return null;
        }
        QuerySightPoiByIdRequest request = new QuerySightPoiByIdRequest();
        request.setPoiId(PoiId);
        BizResponse<SightPoiDetailResponse> bizResponse = sightPoiRemote.querySightPoiById(request);
        if (bizResponse == null || !bizResponse.isSuccess() || bizResponse.getData() == null) {
            log.error("RestaurantInfoService#queryRestaurantDetailByPoiId 根据POI查询详情失败，数据为空 入参：【{}】，出参：【{}】", JSONObject.toJSONString(request), JSONObject.toJSONString(bizResponse));
            return null;
        }
        return FoodConvert.convertToRestaurantDetailBO(FoodConvert.convertToRestaurantInfoBO(restaurantInfoPO), bizResponse.getData());
    }

    @Override
    public PageResult<RestaurantInfoBO> queryRestaurantInfoByCondition(RestaurantInfoConditionBO conditionBO) {
        if (conditionBO == null) {
            return new PageResult<>();
        }
        RestaurantInfoCondition condition = FoodConvert.convertToRestaurantInfoCondition(conditionBO);
        PageResult<RestaurantInfoPO> pageResult = restaurantInfoRepository.queryRestaurantInfoByCondition(condition);
        if (pageResult == null) {
            return new PageResult<>();
        }
        PageResult<RestaurantInfoBO> result = new PageResult<>();
        result.setResults(pageResult.getResults() == null ? null : pageResult.getResults().stream().map(FoodConvert::convertToRestaurantInfoBO).collect(Collectors.toList()));
        result.setPageCount(pageResult.getPageCount());
        result.setCurrentIndex(pageResult.getCurrentIndex());
        result.setTotal(pageResult.getTotal());
        result.setPageSize(pageResult.getPageSize());
        result.setHasNext(pageResult.isHasNext());
        return result;
    }

    @Override
    public List<RestaurantInfoBO> queryRestaurantInfoByIdList(List<Long> restaurantIdList) {
        if (CollectionUtils.isEmpty(restaurantIdList)) {
            return Lists.newArrayList();
        }
        if (restaurantIdList.size() > MAX_QUERY_PAGE_SIZE) {
            log.warn("RestaurantInfoService#queryRestaurantInfoByIdList 查询饭店信息列表失败，参数错误，查询数量过大，最大支持100个数据 restaurantIdList：【{}】", restaurantIdList);
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "查询数量过大，最大支持100个数据");
        }
        List<RestaurantInfoPO> restaurantInfoPOList = restaurantInfoRepository.queryRestaurantInfoByIdList(restaurantIdList);
        return FoodConvert.convertToRestaurantInfoBOList(restaurantInfoPOList);
    }

    @Override
    public List<RestaurantInfoBO> queryRestaurantInfoByName(String restaurantName) {
        if (StringUtils.isBlank(restaurantName)) {
            return Collections.emptyList();
        }
        List<RestaurantInfoPO> restaurantInfoPOList = restaurantInfoRepository.queryRestaurantInfoByName(restaurantName);
        return FoodConvert.convertToRestaurantInfoBOList(restaurantInfoPOList);
    }
}
